using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using HslCommunicationEx;

namespace AcqEncoder.TcpIp
{
	public class TcpServerSimple
	{
		public delegate void RemoveAllUserDelegate(string ip, string port);

		private delegate void ListenClientDelegate(out TcpClient client);

		private static readonly object RemoveLock = new object();

		private static readonly object RemoveUserLock = new object();

		public Func<TcpClient, RemoteTcpClient> ConClientHandler;

		public static List<RemoteTcpClient> UserList = new List<RemoteTcpClient>();

		public static bool ExistListen;

		private TcpListener _clientListener;

		public bool ReadAuto { get; set; } = true;


		public Action<RemoteTcpClient, OperateRet> TcpClientErrorHandler { get; set; }

		public OperateRet StartListen(string ip, int port, int listenTime)
		{
			OperateRet operateRet = new OperateRet();
			if (this._clientListener != null)
			{
				operateRet.Message = "监听已经启动";
				return operateRet;
			}
			TcpServerSimple.ExistListen = false;
			IPAddress setLocalAddress = IPAddress.Parse(ip);
			if (!Dns.GetHostAddresses(Dns.GetHostName()).Any((IPAddress x) => x.ToString().Equals(setLocalAddress.ToString())) && !(ip == "127.0.0.1"))
			{
				operateRet.Message = "监听地址不存在";
				return operateRet;
			}
			this._clientListener = new TcpListener(setLocalAddress, port);
			this._clientListener.Start();
			Thread thread = new Thread((ThreadStart)delegate
			{
				this.ListenClientConnect(listenTime);
			});
			thread.IsBackground = true;
			thread.Start();
			operateRet.Success = true;
			return operateRet;
		}

		private void ListenClientConnect(int listenTime)
		{
			while (true)
			{
				TcpClient newClient = null;
				Task task = new Task(delegate
				{
					this.AccentClient(out newClient);
				});
				task.Start();
				while (!task.IsCompleted && !TcpServerSimple.ExistListen)
				{
					Thread.Sleep(listenTime);
				}
				if (newClient == null)
				{
					break;
				}
				RemoteTcpClient remoteTcpClient = this.ConClientHandler?.Invoke(newClient);
				if (remoteTcpClient == null)
				{
					continue;
				}
				remoteTcpClient.ReadOutHandler = (Action<string, int>)Delegate.Combine(remoteTcpClient.ReadOutHandler, new Action<string, int>(RemoveUser));
				if (remoteTcpClient.IsReadMutiThread)
				{
					OperateRet operateRet = remoteTcpClient.StartReadTask();
					if (!operateRet.Success)
					{
						this.TcpClientErrorHandler?.Invoke(remoteTcpClient, operateRet);
					}
				}
				lock (TcpServerSimple.RemoveLock)
				{
					TcpServerSimple.UserList.Add(remoteTcpClient);
				}
			}
		}

		private void AccentClient(out TcpClient newClient)
		{
			try
			{
				newClient = this._clientListener.AcceptTcpClient();
			}
			catch
			{
				newClient = null;
			}
		}

		public OperateRet SynSendToClient(string ip, int port, string msg)
		{
			OperateRet operateRet = new OperateRet();
			if (string.IsNullOrEmpty(ip))
			{
				throw new ArgumentNullException("ip");
			}
			if (string.IsNullOrEmpty(msg))
			{
				throw new ArgumentNullException("msg");
			}
			if (TcpServerSimple.UserList.Count == 0)
			{
				operateRet.Message = "不存在连接用户信息";
				return operateRet;
			}
			RemoteTcpClient remoteTcpClient = TcpServerSimple.UserList.FirstOrDefault((RemoteTcpClient x) => x.UserIp.Equals(ip) && x.UserPort == port);
			if (remoteTcpClient == null)
			{
				operateRet.Message = "指定用户信息不存在";
				return operateRet;
			}
			operateRet.Success = remoteTcpClient.SendData(msg) == true;
			return operateRet;
		}

		public bool? SynSendToClient(string ip, int port, byte[] sendBuf)
		{
			if (TcpServerSimple.UserList.Count == 0)
			{
				return false;
			}
			return TcpServerSimple.UserList.FirstOrDefault((RemoteTcpClient x) => x.UserIp.Equals(ip) && x.UserPort == port)?.SendData(sendBuf);
		}

		public void SyncSendToAllClient(string msg)
		{
			foreach (RemoteTcpClient user in TcpServerSimple.UserList)
			{
				user.SendData(msg);
			}
		}

		public void SyncSendToAllClient(byte[] sendBuf)
		{
			foreach (RemoteTcpClient user in TcpServerSimple.UserList)
			{
				user.SendData(sendBuf);
			}
		}

		public void RemoveUser(string ip, int port)
		{
			if (ip == null)
			{
				throw new ArgumentNullException("ip");
			}
			lock (TcpServerSimple.RemoveUserLock)
			{
				List<RemoteTcpClient> list = TcpServerSimple.UserList.Where((RemoteTcpClient x) => x.UserIp.Equals(ip) && x.UserPort == port).ToList();
				foreach (RemoteTcpClient item in list)
				{
					TcpServerSimple.UserList.Remove(item);
					Task.Run(new Action(item.Dispose));
				}
			}
		}

		public void DisposeAll()
		{
			try
			{
				while (TcpServerSimple.UserList.Count > 0)
				{
					TcpServerSimple.UserList[0].Dispose();
					lock (TcpServerSimple.RemoveLock)
					{
						TcpServerSimple.UserList.Remove(TcpServerSimple.UserList[0]);
					}
				}
				this.StopListen();
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		public void StopListen()
		{
			TcpServerSimple.ExistListen = true;
			this._clientListener?.Stop();
			this._clientListener = null;
		}

		public static bool CheckNet(string ip, int timeout = 3000)
		{
			Ping ping = new Ping();
			for (int i = 0; i < 3; i++)
			{
				PingReply pingReply = ping.Send(ip, timeout);
				if (pingReply != null && pingReply.Status == IPStatus.Success)
				{
					return true;
				}
			}
			return false;
		}
	}
}
